#ifndef __MY_DATA__
#define __MY_DATA__

#include "util.hpp"
#include "config.hpp"
#include <unordered_map>
#include <pthread.h>

namespace cloud{
    typedef struct BackupInfo{
        bool pack_flag;//压缩标志位;
        size_t fsize;//文件大小;
        time_t mtime;//最后修改时间;
        time_t atime;//最后访问时间;
        std::string real_path;//真实路径;
        std::string pack_path;//压缩路径;
        std::string url;
        bool NewBackupInfo(const std::string& realpath){
            FileUtil fu(realpath);
            if(fu.Exists() == false){ //判断文件是否存在
                std::cout << "new backupinfo: file not exit!\n";
                return false;
            }
            Config* config = Config::GetInstance();
            //获取对应文件信息
            std::string packdir = config->GetPackDir();
            std::string packsuffix = config->GetPackFileSuffix();
            std::string download_prefix = config->GetDownLoadPrefix();
            this->pack_flag = false;
            this->fsize = fu.FileSize();
            this->mtime = fu.LastMTime();
            this->atime = fu.LastATime();
            this->real_path = realpath;
            // ./backdir/a.txt   ->   ./packdir/a.txt.lz
            this->pack_path = packdir + fu.Filename() + packsuffix;
            // ./backdir/a.txt   ->   ./download/a.txt 
            this->url = download_prefix + fu.Filename();
            return true;
        }
    }BackupInfo;

    class DataManager{
        public:
            DataManager(){
                _backup_file = Config::GetInstance()->GetBackupFile();
                pthread_rwlock_init(&_rwlock, nullptr); //初始化读写锁
                InitLoad(); //初始化加载数据文件
            }
            ~DataManager(){
                pthread_rwlock_destroy(&_rwlock);
            }
            bool Insert(const BackupInfo& info){
                pthread_rwlock_wrlock(&_rwlock);
                _table[info.url] = info;
                pthread_rwlock_unlock(&_rwlock);
                Storage();
                return true;
            }
            bool Updata(const BackupInfo& info){
                pthread_rwlock_wrlock(&_rwlock);
                _table[info.url] = info;
                pthread_rwlock_unlock(&_rwlock);
                Storage();
                return true;
            }
            bool GetOneByURL(const std::string& url, BackupInfo* info){
                pthread_rwlock_rdlock(&_rwlock) ;
                auto it = _table.find(url);
                if(it == _table.end()){ //没找到该文件
                    pthread_rwlock_unlock(&_rwlock);
                    return false;
                }
                *info = it->second;
                pthread_rwlock_unlock(&_rwlock);
                return true;
            }
            bool GetOneByRealPath(const std::string& realpath, BackupInfo* info){
                pthread_rwlock_rdlock(&_rwlock) ;
                auto it = _table.begin();
                while(it != _table.end()){
                    if(it->second.real_path == realpath){
                        *info = it->second;
                        pthread_rwlock_unlock(&_rwlock);
                        return true;
                    }
                    ++it;
                }
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            bool GetAll(std::vector<BackupInfo>* arry){
                pthread_rwlock_rdlock(&_rwlock);
                auto it = _table.begin();
                while(it != _table.end()){
                    arry->push_back(it->second);
                    ++it;
                }
                pthread_rwlock_unlock(&_rwlock);
                return true;
            }
            //持久化存储
            bool Storage() {
                //1.获取所有数据
                std::vector<BackupInfo> arry;
                this->GetAll(&arry);
                //2.添加到Json::Value
                Json::Value root;
                for(int i=0; i<arry.size(); ++i){
                    Json::Value tmp;
                    tmp["pack_flag"] = arry[i].pack_flag;
                    tmp["fsize"] = (Json::Int64)arry[i].fsize;
                    tmp["mtime"] = (Json::Int64)arry[i].mtime;
                    tmp["atime"] = (Json::Int64)arry[i].atime;
                    tmp["real_path"] = arry[i].real_path;
                    tmp["pack_path"] = arry[i].pack_path;
                    tmp["url"] = arry[i].url;
                    root.append(tmp);//添加数组元素
               }
                //3.对Json::Value进行序列化
                std::string body;
                JsonUtil::Serialize(root, &body);
                //4.写文件
                FileUtil fu(_backup_file);
                fu.SetContent(body);
                return true;
            }
            bool InitLoad(){
            //1.将文件中数据读取出来
            FileUtil fu(_backup_file);
            if(fu.Exists() == false){
                return true;
            }
            //2.反序列化
            std::string body;
            fu.GetContent(&body);
            std::cout << "data.hpp  -->InitLoad" <<std::endl << body << std::endl;//////////////////////////
            //3.将反序列化得到的Json::Value中的数据添加到table中
            Json::Value root;
            JsonUtil::UnSerialize(body, &root);
            for(int i=0; i<root.size(); ++i){
                BackupInfo info;
                info.pack_flag = root[i]["pack_flag"].asBool();
                info.fsize = root[i]["fsize"].asInt64();
                info.atime = root[i]["atime"].asInt64();
                info.mtime = root[i]["mtime"].asInt64();
                info.pack_path = root[i]["pack_path"].asString();
                info.real_path = root[i]["real_path"].asString();
                info.url = root[i]["url"].asString();
                Insert(info);
            }
        } 

        private:
            std::string _backup_file;
            pthread_rwlock_t _rwlock;
            std::unordered_map<std::string, BackupInfo> _table;
    };
}


#endif